#include <stdlib.h>
#include <stdio.h>
#include "chunk.h"
#include "mem.h"
#include "vm.h"

void initChunk(Chunk *chunk) {
    chunk->capacity = 0;
    chunk->count = 0;
    chunk->code = NULL;
    chunk->lines = NULL;
    initValueArray(&chunk->constants);
}

void freeChunk(Chunk *chunk) {
    FREE_ARRAY(uint8_t, chunk->code, chunk->capacity);
    freeValueArray(&chunk->constants);
    initChunk(chunk);
}

void writeChunk(Chunk *chunk, uint8_t byte, int line) {
    if (chunk->capacity < chunk->count + 1) {
        int oldCapacity = chunk->capacity;
        chunk->capacity = GROW_CAPACITY(chunk->capacity);
        chunk->code = GROW_ARRAY(uint8_t, chunk->code, oldCapacity, chunk->capacity);
        chunk->lines = GROW_ARRAY(int, chunk->lines, oldCapacity, chunk->capacity);
    }

    chunk->code[chunk->count] = byte;
    chunk->lines[chunk->count] = line;
    chunk->count++;
}

void writeConstant(Chunk *chunk, Value value, int line) {
    int constant = addConstant(chunk, value);
    if (constant > 255) {
        writeChunk(chunk, OP_CONSTANT_LONG, line);
        for(int i = 2; i >= 0; i--) {
            writeChunk(
                chunk,
                (constant >> (i * 8)) & 0xff,
                line
            );
        }
    } else {
        writeChunk(chunk, OP_CONSTANT, line);
        writeChunk(chunk, constant, line);
    }
}

int addConstant(Chunk *chunk, Value value) {
    push(value);
    writeValueArray(&chunk->constants, value);
    // printf("add constant: ");
    // printValue(value);
    // printf(", idx: %d\n", chunk->constants.count - 1);
    pop();
    return chunk->constants.count - 1;
}